Einfache Transparenz
Die meisten Spezialeffekte in OpenGL basieren auf einer Art Blending. Blending wird benutzt, um die Farbe eines bestimmten Pixels, der gezeichnet werden soll, mit einem Pixel, der bereits auf dem Bildschirm ist, zu kombinieren. Wie die Farben kombiniert werden basiert auf dem Alpha Wert der Farben und/oder die Blending Funktion, die benutzt wird. Alpha ist die 4te Farbkomponente, die normalerweise an letzter Stelle spezifiziert wird. In der Vergangenheit haben Sie GL_RGB benutzt, um Farben mit 3 Komponenten zu spezifizieren. GL_RGBA kann benutzt werden, um auch Alpha zu spezifizieren. Zusätzlich können wir glColor4f() statt glColor3f() benutzen.
Die meisten Leute stellen sich Alpha als einen Wert vor, der angibt, wie durchsichtig das Material ist. Ein Alpha-Wert von 0.0 bedeutet, dass das Material komplett transparent ist. Ein Wert von 1.0 würde totale Undurchsichtigkeit bedeuten.
Die Blending Gleichung
Wenn Sie Mathe nicht mögen und Sie nur wissen wollen, wie das mit der Transparenz funktioniert, können Sie diesen Teil überspringen. Wenn Sie wissen wollen, wie Blending funktioniert, dann ist dieser Abschnitt genau das richtige für Sie.
(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
OpenGL berechnet das Ergebnis des Blendings der zwei Pixel basierend auf dieser Gleichung durchführen. Das s und d beschreiben den Quell- und den Ziel-Pixel. Die S und D Komponenten sind die Blend-Faktoren. Diese Werte indizieren, wie Sie die Pixel blenden wollen. Die häufigsten Werte für S und D sind (As, As, As, As) (auch bekannt als Quell Alpha) für S und (1, 1, 1, 1) - (As, As, As, As) (auch bekannt als 1 minus Quell-Alpha) für D. Daraus resultiert eine Blending-Gleichung, die wie folgt aussieht:
(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bd (1 - As), As As + Ad (1 - As))
Diese Gleichung hat als Ergebnis Transparente/Lichtdurchlässige Effekte.
Blending in OpenGL
Wir aktivieren Blending wie alles anderes auch. Dann setzen wir die Gleichung und deaktivieren das Schreiben in den Depth Buffer solange wir transparente Objekte zeichnen, da wir die Objekte, die hinter der durchsichtigen Fläche sind, auch noch zeichnen wollen. Das ist nicht der korrekte Weg für Blending, aber bei den meisten einfachen Objekten funktioniert das wunderbar. Rui Martins fügt hinzu: Der korrekte Weg ist, alle transparenten Polygone (mit Alpha < 1.0) zu zeichnen, nachdem Sie die komplette Szene gezeichnet haben und diese in umgekehrter Tiefen-Ordnung (das entfernteste als erstes) zu zeichen. Das liegt daran, dass beim blenden zweier Polygone (1 und 2) in verschiedener Reihenfolge, es verschiedene Ergebnisse gibt, z.B. angenommen Polygon 1 ist am nähsten zum Betrachter, der korrekte Weg wäre, Polygon 2 als erstes zu zeichnen und dann Polygon 1. Wenn sie drauf schauen, kommt das Licht, wie in der Realität von hinten (hinter der 2 Polygonen, die transparent sind) und muss Polygon 2 als erstes und dann Polygon 1 passieren, bevor es das Auge des Betrachters erreicht. Sie sollten DIE TRANSPARENTEN POLYGONE DER TIEFE NACH SORTIEREN und sie NACHDEM DIE GESAMTE SZENE GEZEICHNET WURDE zeichnen, mit AKTIVIERTEN DEPTH BUFFER oder Sie erhalten unkorrekte Ergebnisse. Ich weiß, dass das manchmal nervig ist, aber das ist der korrekte Weg.
Wir werden den Code aus dem letzten Tutorial benutzen. Wir starten mit dem Hinzufügen zweier neuer Variablen am Anfang des Codes. Ich werde den kompletten Code-Ausschnitt der Klarheit halber hier nochmal komplett neu schreiben.
#include < windows.h> // Header Datei für Windows
#include < stdio.h> // Header Datei für die Standard Ein-/Ausgabe
#include < gl\gl.h> // Header Datei für die OpenGL32 Library
#include < gl\glu.h> // Header Datei für die GLu32 Library
#include < gl\glaux.h> // Header Datei für die GLaux Library
HDC hDC=NULL; // Privater GDI Device Context
HGLRC hRC=NULL; // Permanenter Rendering Context
HWND hWnd=NULL; // Enthält unser Fenster-Handle
HINSTANCE hInstance; // Enthält die Instanz der Applikation
bool keys[256]; // Array das für die Tastatur Routine verwendet wird
bool active=TRUE; // Fenster Aktiv Flag ist standardmäßig auf TRUE gesetzt
bool fullscreen=TRUE; // Fullscreen Flag ist standardmäßig gesetzt
bool light; // Beleuchtung AN/AUS
bool blend; // Blending AUS/AN? ( NEW )
bool lp; // L gedrückt?
bool fp; // F gedrückt?
bool bp; // B gedrückt? ( NEU )
GLfloat xrot; // X Rotation
GLfloat yrot; // Y Rotation
GLfloat xspeed; // X Rotationsgeschwindigkeit
GLfloat yspeed; // Y Rotationsgeschwindigkeit
GLfloat z=-5.0f; // Tiefe in den Bildschirm hinein
GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; // Ambiente Licht Werte
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; // Diffuse Licht Werte
GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f }; // Licht Position
GLuint filter; // Welcher Filter benutzt werden soll
GLuint texture[3]; // Speicher für 3 Texturen
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Deklaration für WndProc
if (TextureImage[0]=LoadBMP("Data/glass.bmp")) // Lädt das Glass Bitmap ( MODIFIZIERT )
glColor4f(1.0f,1.0f,1.0f,0.5f); // Volle Helligkeit, 50% Alpha ( NEU ) glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Blending Funktion für Durchsichtigkeit basiered auf dem Quell Alpha Wert ( NEU )
if (keys[VK_LEFT]) // Wurde die linke Pfeil-Taste gedrückt?
{
yspeed-=0.01f; // Wenn ja, dekrementiere yspeed
}
if (keys['B'] && !bp) // Ist Taste B gedrückt und bp gleich FALSE?
{
bp=TRUE; // Wenn ja, setze bp auf TRUE
blend = !blend; // Tausche den Status von blend auf TRUE / FALSE
if(blend) // Ist blend gleich TRUE?
{
glEnable(GL_BLEND); // Schalte Blending ein
glDisable(GL_DEPTH_TEST); // Schalte Depth Testing aus
}
else // Ansonsten
{
glDisable(GL_BLEND); // Schalte Blending aus
glEnable(GL_DEPTH_TEST); // Schalte Depth Testing an
}
}
if (!keys['B']) // Wurde die B Taste losgelassen?
{
bp=FALSE; // Wenn ja, wird bp auf FALSE gesetzt
}